<template>
  <div class="basic-upload">
    <!--上传图片-->
    <div
      class="basic-upload-list"
      :class="{ 'hide-upload': hideUpload, 'circle-upload': props.circle }"
    >
      <el-upload
        v-bind="$props"
        :before-remove="beforeRemove"
        :before-upload="beforeUpload"
        @preview="preview"
        @remove="remove"
        @exceed="exceed"
        :file-list="getFileList"
        @success="finish"
      >
        <!-- 卡片，列表 多图上传 -->
        <template v-if="props.listType === 'picture-card'">
          <el-icon v-if="!$slots.icon"><Plus /></el-icon>
          <slot name="icon"></slot>
        </template>
        <template v-else
          ><el-button type="primary">{{ props.uploadTitle }}</el-button></template
        >
        <!--规则提示-->
        <template #tip>
          <div v-if="getHelpText" class="basic-upload-alert">
            <el-alert title="提示" type="warning" v-if="getHelpText" class="flex w-full">
              {{ getHelpText }}
            </el-alert>
          </div>
        </template>
      </el-upload>
    </div>
  </div>

  <!--预览图片-->
  <el-dialog v-model="showModal" title="预览" draggable>
    <img style="width: 100%" :src="previewUrl" />
  </el-dialog>
</template>

<script lang="ts" setup>
  import { ref, computed } from 'vue';
  import { Plus } from '@element-plus/icons-vue';
  import { basicProps } from './props';
  import { ElMessage, ElMessageBox } from 'element-plus';
  import { ResultEnum } from '@/enums/httpEnum';
  import componentSetting from '@/settings/componentSetting';
  import { useGlobSetting } from '@/hooks/setting';
  import { isString } from '@/utils/is';
  import type { UploadFile, UploadRawFile } from 'element-plus';
  import { isNumber } from 'lodash-es';
  import type { Ifiles } from './type/index';

  const globSetting = useGlobSetting();

  const props = defineProps({ ...basicProps });

  const getHelpText = computed(() => {
    return props.helpText;
  });

  const emit = defineEmits(['uploadChange', 'delete']);

  const getWidth = computed(() => {
    return isNumber(props.width) ? `${props.width}px` : props.width;
  });

  const showModal = ref(false);
  const previewUrl = ref('');
  const fileList = ref<Ifiles[]>([]);

  const hideUpload = computed(() => {
    if (!props.limit) return false;
    return fileList.value.length >= props.limit;
  });

  const getFileList = computed(() => {
    return props.list.map((item: any) => {
      return { url: getImgUrl(item.url) };
    });
  });

  //预览
  function preview(file: UploadFile) {
    previewUrl.value = file.url!;
    showModal.value = true;
  }

  //删除之前
  async function beforeRemove(file) {
    if (file && file.status === 'success') {
      const res = await ElMessageBox.confirm('你确定要删除吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).catch(() => {});
      return res === 'confirm' ? true : false;
    }
  }

  //删除
  function remove(_, resFileList: UploadFile[]) {
    fileList.value = getResponseImgUrls(resFileList);
    emit('uploadChange', fileList.value);
    emit('delete', fileList.value);
  }

  //获取服务端返回图片地址
  function getResponseImgUrls(list) {
    const urls: any[] = [];
    const { infoField, imgField } = componentSetting.upload.apiSetting;
    list.forEach((item) => {
      const info = {
        status: item.status || 'success',
        uid: item.uid || '',
        url: item.url || '',
      };
      if (item.response) {
        const result = item.response[infoField];
        const path = result[imgField];
        if (path) {
          info.url = path;
        }
      }
      urls.push(info);
    });
    return urls;
  }

  //组装完整图片地址
  function getImgUrl(url: string): string {
    const { imgUrl } = globSetting;
    return /(^http|https:\/\/)/g.test(url) ? url : `${imgUrl}${url}`;
  }

  function checkFileType(fileType: string) {
    return componentSetting.upload.fileType.includes(fileType);
  }

  //上传之前
  function beforeUpload(file: UploadRawFile) {
    const { maxSize, accept } = props;
    const acceptRef = (isString(accept) && accept.split(',')) || [];

    // 设置最大值，则判断
    if (maxSize && file.size / 1024 / 1024 >= maxSize) {
      ElMessage({
        message: `上传文件最大值不能超过${maxSize}M`,
        type: 'error',
      });
      return false;
    }

    // 设置类型,则判断
    const fileType = componentSetting.upload.fileType;
    if (acceptRef.length > 0 && !checkFileType(file.type)) {
      ElMessage({
        message: `只能上传文件类型为${fileType.join(',')}`,
        type: 'error',
      });
      return false;
    }

    return true;
  }

  //上传结束
  function finish(response: any, file: UploadFile, resFileList: UploadFile[]): void {
    try {
      const res = response;
      const { code } = res;
      const msg = res.msg || res.message || '上传失败';
      //成功
      if (code === ResultEnum.SUCCESS) {
        fileList.value = getResponseImgUrls(resFileList);
        emit('uploadChange', fileList.value);
      } else {
        ElMessage({
          message: msg,
          type: 'error',
        });
      }
    } catch (error) {
      console.error(error);
    }
  }

  //超出限制
  function exceed() {
    ElMessage({
      message: `超出数量限制，最多可上传${props.limit}个文件`,
      type: 'error',
    });
  }
</script>

<style lang="scss" scoped>
  .basic-upload {
    max-width: 100%;
    &-alert {
      margin-top: 10px;
    }

    :deep(.hide-upload .el-upload-list .el-upload) {
      display: none;
    }
    :deep(.el-upload-list--picture-card) {
      --el-upload-list-picture-card-size: v-bind(getWidth);
    }
    :deep(.el-upload--picture-card) {
      --el-upload-picture-card-size: v-bind(getWidth);
    }

    //圆角
    :deep(.circle-upload .el-upload--picture-card, .el-upload-list__item) {
      border-radius: 50%;
    }
    :deep(.circle-upload .el-upload-list__item) {
      border-radius: 50%;
    }
  }
</style>
